import {Component, forwardRef, Input, ViewChild} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
import {GnUuidUtils} from 'geminis-ng-core';
import {GnFormItem, GnFormItemConfig, GnJsonFormComponent} from 'geminis-ng';
import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop';
import {HttpClient} from '@angular/common/http';
import {NzModalRef, NzModalService} from 'ng-zorro-antd/modal';

let __this;

@Component({
  selector: 'everydata-form-items',
  styleUrls: ['form-items.component.less'],
  templateUrl: 'form-items.component.html',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => FormItemsComponent),
      multi: true
    },
    {
      provide: NzModalRef,
      useValue: null
    }
  ]
})
@GnFormItem('everydata-form-items')
export class FormItemsComponent implements ControlValueAccessor {

  selectedItemConfig!: GnFormItemConfig;
  innerValue: GnFormItemConfig[] = [];
  components: any[] = [];
  @ViewChild('propertyBasic') propertyBasicForm!: GnJsonFormComponent;
  @ViewChild('propertyExternal') propertyExternalForm!: GnJsonFormComponent;

  @Input() set value(v: GnFormItemConfig[]) {
    if (v === this.innerValue) {
      return;
    }

    if (!v) {
      v = [];
    }
    this.innerValue = v.sort((p1, p2) => p1.showOrder - p2.showOrder);
    this.onValueChange();
  }

  get value(): GnFormItemConfig[] {
    return this.innerValue;
  }

  valueChange = (value: GnFormItemConfig[]) => {
  };

  constructor(public jsonForm: GnJsonFormComponent,
              private modalService: NzModalService,
              private http: HttpClient) {
    __this = this;
    http.get('/everydata-pc/assets/config/form-component.json')
      .subscribe((value: any): void => {
        this.components = value;
      });
  }

  registerOnChange(fn: any): void {
    this.valueChange = fn;
  }

  registerOnTouched(fn: any): void {
  }

  setDisabledState(isDisabled: boolean): void {
  }

  writeValue(obj: any): void {
    this.value = obj;
  }

  private onValueChange(): void {
    this.valueChange(this.innerValue);
  }

  selectItem(value: GnFormItemConfig): void {
    if (value === this.selectedItemConfig) {
      return;
    }
    this.propertyExternalForm.form.bindValue = {};

    this.selectedItemConfig = value;
    this.propertyBasicForm.form.bindValue = value;
    for (const key of Object.keys(this.propertyExternalForm.form.formGroup.controls)) {
      this.propertyExternalForm.form.formGroup.removeControl(key);
    }
    this.propertyExternalForm.form.formGroup.setValue({});
    this.propertyExternalForm.url = '/everydata-pc/assets/forms/form/form-item-property-external-' + this.selectedItemConfig.type + '.json';
  }

  loadExternalConfig(): void {
    if (this.selectedItemConfig) {
      if (!this.selectedItemConfig.options) {
        this.selectedItemConfig.options = {};
      }
      this.propertyExternalForm.form.bindValue = this.selectedItemConfig.options;
    }
  }

  deleteItem(config: GnFormItemConfig): void {
    this.modalService.confirm({
      nzContent: '确定删除该数据项？',
      nzOnOk: () => {
        this.innerValue.splice(this.innerValue.indexOf(config), 1);
        this.onValueChange();
      }
    });
  }

  drop(event: CdkDragDrop<number>) {
    if (event.previousContainer.id === 'componentsDropList' && event.container.id !== 'componentsDropList') {
      const item = this.components[event.previousIndex];
      let field = '';
      if (item.field) {
        field = item.field + '_' + GnUuidUtils.uuid();
      }
      this.innerValue.splice(event.container.data, 0, {
        field: field,
        showOrder: 0,
        colspan: 1,
        rowspan: 1,
        label: item.label,
        type: item.type
      });
    } else if (event.previousContainer !== event.container || event.previousIndex !== event.currentIndex) {
      moveItemInArray(this.innerValue, event.previousContainer.data, event.container.data);
    }

    for (let i = 0; i < this.innerValue.length; i++) {
      this.innerValue[i].showOrder = i;
    }

    this.onValueChange();
  }

  dropDisable(): boolean {
    return false;
  }
}
